/******************************************************************************
Copyright:
2009 Jens Collin (jens.collin@dinomin.com)

This file is part of Envox Decompiler.

Envox Decompiler is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Envox Decompiler is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KitchenOS.  If not, see <http://www.gnu.org/licenses/>.

******************************************************************************/
using System;
using System.Collections;

namespace EnvoxDecompiler
{
	/// <summary>
	/// Summary description for Block_DBClose.
	/// </summary>
	public class Block_DBClose : Block
	{
	
		enum OPERATIONTYPES
		{
			CloseDB = 0,
			CloseRS = 1,
			CloseRSFromDB = 2,
			CloseAllRS = 3
		}

		private OPERATIONTYPES _operationType;
		private int _commit;
		private string _database = "";
		private ArrayList _recordsets = new ArrayList();
    

		public override TYPE GetBlockType()
		{
			return TYPE.DBClose;
		}

		public override string GetXML(int x, int y)
		{
			Trace.Debug("Block_DBClose::GetXML Started.");	
			// <DbClose name="NAME" rect="X 32 96 56"
            string xml = "\t\t\t<DbClose name=\"" + Utils.XmlString(_name) + "\" rect=\"" + x + " " + y + " 96 56\"";
			//  ...description="DESC"...
			xml += GetDescriptionXML();
			//  ...clearDTMF="_clearDTMFBuffer"...
			xml += GetClearDTMFXML();
			// ...minUserLevel="_userLevel"
			xml += GetMinUserLevelXML();
			// ...cpMessage=""...
			xml += GetControlPanelMessageXML();

			// ...database="DB"...
			xml += " database=\"" + Utils.XmlString(_database) + "\"";
			// ...commit="COMMIT"...
			xml += " commit=\"" + _commit + "\"";
			// ...type="TYPE"...
			xml += " type=\"" + (int)_operationType + "\"";

			// End the header xml-part.
			xml += ">\r\n";

			// <Inputs>
			xml += GetInputsXML(_blockId);
		
			// <Outputs>
			xml += GetOutputsXML();

			// <Logs>
			xml += GetLogsXML();
			
			xml += GetHandledErrorsXML();

			// <Recordsets>
			xml +="\t\t\t\t<Recordsets>\r\n";
			foreach (string rs in _recordsets)
			{
				xml +="\t\t\t\t\t<Element value=\"" + Utils.XmlString(rs) + "\"/>\r\n";
			}
			xml +="\t\t\t\t</Recordsets>\r\n";

			// </DbClose>
			xml +="\t\t\t</DbClose>\r\n";
			return xml;
		}

		private bool ReadCloseDatabase()
		{
			Trace.Debug("ReadCloseDatabase");
			_commit = _rawData[_currentPos + 2];

			_currentPos += 4;

			_database = Utils.DataToString(_rawData, _currentPos);
			_currentPos = _currentPos + Utils.DataStringLength(_rawData, _currentPos);

			Trace.Debug("_commit = " + _commit +
				", _database = " + _database);
			return true;
		}



		private bool ReadCloseRecordsets()
		{
			Trace.Debug("ReadCloseRecordsets");

			_currentPos += 4;

			string rs = "!"; // Just not ""
			while (rs != "")
			{
				rs = Utils.DataToString(_rawData, _currentPos);
				_currentPos = _currentPos + Utils.DataStringLength(_rawData, _currentPos);
				if (rs != "")
				{
					_recordsets.Add(rs);
					Trace.Debug("Add recordset: " + rs);
				}
			}
			return true;
		}


		private bool ReadCloseRecordsetsFromDatabase()
		{
			Trace.Debug("ReadCloseRecordsetsFromDatabase");
			_currentPos += 4;
			
			_database = Utils.DataToString(_rawData, _currentPos);
			_currentPos = _currentPos + Utils.DataStringLength(_rawData, _currentPos);

			Trace.Debug("_database = " + _database);
			return true;
		}

		private bool ReadCloseAllRecordsets()
		{
			Trace.Debug("ReadCloseAllRecordsets");
			return true;
		}


		public Block_DBClose(byte[] rawData) : base(rawData)
		{
			Trace.Debug("Block_DBClose created.");
			
			outputErrorIds.Add(new BlockOutput(OUTPUT.Next, 0));
			outputErrorIds.Add(new BlockOutput(OUTPUT.DbFailed, 38));
			outputErrorIds.Add(new BlockOutput(OUTPUT.DbTimeout, 34));
			outputErrorIds.Add(new BlockOutput(OUTPUT.DbLocked, 32));
			outputErrorIds.Add(new BlockOutput(OUTPUT.DbAuthorize, 33));
			outputErrorIds.Add(new BlockOutput(OUTPUT.ConnectFailed, 31));
			outputErrorIds.Add(new BlockOutput(OUTPUT.SQLFailed, 168));

			_currentPos += 8;
			
			_operationType = (OPERATIONTYPES)rawData[_currentPos];
			switch (_operationType)
			{
				case OPERATIONTYPES.CloseDB:
					ReadCloseDatabase();
					break;
				
				case OPERATIONTYPES.CloseRS:
					ReadCloseRecordsets();
					break;

				case OPERATIONTYPES.CloseRSFromDB:
					ReadCloseRecordsetsFromDatabase();
					break;

				case OPERATIONTYPES.CloseAllRS:
					ReadCloseAllRecordsets();
					break;

				default:
					Settings.Instance.Unimplemented("Block_DBClose");
					// TODO: Unhandled type.
					AddToBlockNote("This block '" + _name + "' has not been fully implemented in the decompiler. Stuff will be missing.");

					Trace.Debug("Unknown operation type: " + _operationType);
					Trace.Info("DBClose block contains unsupported data, this will make it uncompilable. A dummy block will be inserted.");
					break;
			}

		}
	}
}
